import json, socket
import time, datetime


def send_command(s, data):
    for d in data:
        command = json.dumps(d, indent=1)
        print "sending command ", command
        s.send(command)
        response = s.recv(1024)
        print "received response:", response
        return response


TCP_IP = '127.0.0.1'
TCP_PORT = 6543
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))


def add_rule(table, index, out, match):
    data = {
        "params": {
            "index": index,
            "rw": None,
            "mask": None,
            "in": [],
            "table": table,
            "match": match,
            "out": [out]
        },
        "jsonrpc": "2.0",
        "method": "add_rule",
        "id": 1
    }
    result = send_command(s, [data])
    return result


def remove_rule(rule_id):
    data = {"id": 1,
            "jsonrpc": "2.0",
            "method": "remove_rule",
            "params": {
                "node": int(rule_id)
            }
            }
    return send_command(s, [data])

def isct(a, b):
    for i in range(len(a)):
        if a[i] != 'x' and b[i] != 'x' and a[i] != b[i]:
            return False
    return True


conf = [
    {
        's': None,
        'hs': 'xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,10101100,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx',
        'port': 6543
    }, {
        's': None,
        'hs': 'xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,10101011,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx',
        'port': 6544
    }
]



while (True):
    input = raw_input("Enter command:")
    if input == 'lb':
        for i in conf:
            i['s'] = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            i['s'].connect(('127.0.0.1', i['port']))
    if input == 'lb_run':
        with open('datasets/stanford/batch.json') as f:
            data = json.load(f)
            for c in conf:
                for d in data:
                    if d['method'] == 'add_rule' and isct(c['hs'], d['params']['match']):
                        print 'send to' + str(c['port']) + 'at: ' + datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
                        send_command(c['s'], [d])
            # send_command(s, [data])

    if input == 'looprun':
        for i in range(100):
            result = add_rule(10, int(i), 120000,
                              "xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx")
            time.sleep(0.1)
            remove_rule(json.loads(result)['result'])
            time.sleep(0.1)

    if input == "add_rule":
        table = raw_input("Enter table:")
        index = raw_input("Enter index:")
        # in_ports = raw_input("Enter in ports:")
        out_port = raw_input("Enter out port:")
        match = raw_input("Enter match:")
        # mask = raw_input("Enter mask:")
        add_rule(table, index, out_port, match)

    elif input == "linkup":
        src = raw_input("Enter source id:")
        dst = raw_input("Enter target id:")
        data = {"method": "add_link",
                "id": 1,
                "jsonrpc": "2.0",
                "params": {"from_port": int(src),
                           "to_port": int(dst)}
                }
        send_command(s, [data])
    elif input == "linkdown":
        src = raw_input("Enter source id:")
        dst = raw_input("Enter target id:")
        data = {"method": "remove_link",
                "id": 1,
                "jsonrpc": "2.0",
                "params": {"from_port": int(src),
                           "to_port": int(dst)}
                }
        send_command(s, [data])
    elif input == "print":
        tbid = raw_input("Enter table id:")
        data = {"id": 1,
                "jsonrpc": "2.0",
                "method": "print_table",
                "params": {
                    "id": int(tbid)
                }
                }
        send_command(s, [data])
    elif input == "remove":
        rule_id = raw_input("Enter a rule id:")
        remove_rule(rule_id)
    elif input == "end" or input == "q":
        break
